package org.mozhu.simple.rpc.server;

import lombok.extern.slf4j.Slf4j;
import org.mozhu.simple.rpc.server.network.SocketServer;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;

@Slf4j
public class RpcServer {
    private AtomicBoolean startupComplete = new AtomicBoolean(false);
    private AtomicBoolean isShuttingDown = new AtomicBoolean(false);
    private AtomicBoolean isStartingUp = new AtomicBoolean(false);

    private CountDownLatch shutdownLatch;

    private RpcServerConfig serverConfig;

    private SocketServer socketServer;

    public RpcServer(RpcServerConfig serverConfig) {
        this.serverConfig = serverConfig;
    }

    public void awaitShutdown() {
        try {
            shutdownLatch.await();
        } catch (InterruptedException e) {
            log.error("InterruptedException occurs when awaitShutdown", e);
        }
    }

    public void startup() {
        try {
            log.info("starting");
            if (isShuttingDown.get())
                throw new IllegalStateException("RpcServer is still shutting down, cannot re-start!");

            if (startupComplete.get())
                return;

            boolean canStartup = isStartingUp.compareAndSet(false, true);
            if (canStartup) {
                // do startup logic
                this.socketServer = new SocketServer(serverConfig);
                this.socketServer.startup();

                shutdownLatch = new CountDownLatch(1);
                startupComplete.set(true);
                isStartingUp.set(false);

                log.info("started");
            }
        } catch (Throwable t) {
            log.error("Fatal error during RpcServer startup. Prepare to shutdown", t);
        }
    }

    public void shutdown() {
        try {
            log.info("shutting down");
            if (isStartingUp.get())
                throw new IllegalStateException("RpcServer is still starting up, cannot shut down!");

            if (shutdownLatch.getCount() > 0 && isShuttingDown.compareAndSet(false, true)) {
                // TODO do shutdown logic

                startupComplete.set(false);
                isShuttingDown.set(false);
                shutdownLatch.countDown();
                log.info("shut down completed");
            }
        } catch (Throwable t) {
            log.error("Fatal error during RpcServer shutdown.", t);
            isShuttingDown.set(false);
        }
    }
}
